//外观数列
//https://leetcode.cn/problems/count-and-say/description/
public class Test {
    public static void main(String[] args) {
        //
        Solution solution = new Solution();
        String s = solution.countAndSay(4);
        System.out.println(s);
    }
}
//老师讲的写法：
class Solution2 {
    public String countAndSay(int n) {
        //
        String res = "1";
        if(n==1) return "1";
        for(int i = 1;i<n;i++){//解释的次数/行数
            StringBuilder tmp = new StringBuilder();
            int len = res.length();
            for(int left = 0,right = 0; right<len;){//解释的过程——这个for循环的处理过程很巧妙，学着点！！！~~~
                while((right<len)&&(res.charAt(left)==res.charAt(right))){
                    right++;
                }
                tmp.append(Integer.toString(right-left));
                tmp.append(res.charAt(left));
                left = right;
            }
            res = tmp.toString();
        }
        return res;
    }
}

//↓↓↓改对了！！！！
class Solution {
    public String countAndSay(int n) {
        if(n==1){
            return "1";
        }

        StringBuilder s = new StringBuilder();
        s.append(1);

        for(int i = 2;i<=n;i++){
            int len = s.length();//第i行需要扫描的长度（上次扫描出来的字符长长度，即，这次需要被扫描的字符串的长度）
            StringBuilder res = new StringBuilder();

            int flg = 0;
            int left = 0,right = 0;
            char leftElem = s.charAt(left);
            char rightElem = s.charAt(right);
            for(left = 0,right = 0;right<len;right++){//双指针
                leftElem = s.charAt(left);
                rightElem = s.charAt(right);
                if(leftElem == rightElem){
                    if(right==len-1){
                        res.append(Integer.toString(right-left+1));
                        res.append(leftElem);
                        flg = 1;
                    }
                    continue;
                }else{
                    res.append(right-left);//被描述的元素的个数
                    res.append(leftElem);//被描述的元素
                    left=right;
                }
            }

            //s = res;
            if(flg == 0){//利用flg 的情况，判断是从上边哪里退出的（区分出，退出循环的时候是哪种情况）
                //这里有点问题，没有考虑到，当right不符合条件退出循环的时候，之前的left和right的情况是否被统计了
                //似乎情况划分很重要。简单、有效、正确（有点像“测试”中的“等价类”划分）
                res.append(right-left);
                res.append(s.charAt(right - 1));
            }
            s = res;
        }
        return s.toString();
    }
}
